/**
 * @file   PropertyInfo.cpp
 * @author Djuro Drljaca (djurodrljaca@gmail.com)
 * @date   2013-05-16
 * @brief  DataBus Property Info.
 *
 * Copyright (C) 2013 Djuro Drljaca <djurodrljaca@gmail.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <DataBus/Common/PropertyInfo.h>
#include <DataBus/Common/Value.h>

DataBus::PropertyInfo::PropertyInfo()
    : m_id(0),
      m_dataType(DataType_Invalid),
      m_accessPermission(AccessPermission_Invalid),
      m_name()
{
}

DataBus::PropertyInfo::PropertyInfo(const quint8 id,
                                    const DataType dataType,
                                    const AccessPermission accessPermission,
                                    const QString &name)
    : m_id(id),
      m_dataType(DataType_Invalid),
      m_accessPermission(AccessPermission_Invalid),
      m_name()
{
    // Check data type
    if ((dataType < DataType_Boolean) ||
        (dataType > DataType_ByteArray))
    {
        return;
    }

    // Check access permission
    if ((accessPermission < AccessPermission_ReadOnly) ||
        (accessPermission > AccessPermission_ReadWrite))
    {
        return;
    }

    // Check name
    if (name.toUtf8().size() > STRING_MAX_LENGTH)
    {
        return;
    }

    // Save data type, access permission and name
    m_dataType = dataType;
    m_accessPermission = accessPermission;
    m_name = name;
}

DataBus::PropertyInfo::PropertyInfo(const PropertyInfo &copyin)
    : m_id(copyin.m_id),
      m_dataType(copyin.m_dataType),
      m_accessPermission(copyin.m_accessPermission),
      m_name(copyin.m_name)
{
}

DataBus::PropertyInfo & DataBus::PropertyInfo::operator=(const PropertyInfo &rhs)
{
    m_id = rhs.m_id;
    m_dataType = rhs.m_dataType;
    m_accessPermission = rhs.m_accessPermission;
    m_name = rhs.m_name;

    return *this;
}

bool DataBus::PropertyInfo::isValid() const
{
    // Check data type
    if (m_dataType == DataType_Invalid)
    {
        // Data type is invalid
        return false;
    }

    // Valid
    return true;
}

quint8 DataBus::PropertyInfo::getId() const
{
    return m_id;
}

void DataBus::PropertyInfo::setId(const quint8 id)
{
    m_id = id;
}

DataBus::DataType DataBus::PropertyInfo::getDataType() const
{
    return m_dataType;
}

bool DataBus::PropertyInfo::setDataType(const DataType dataType)
{
    // Check data type
    if ((dataType < DataType_Boolean) ||
        (dataType > DataType_ByteArray))
    {
        return false;
    }

    // Save data type
    m_dataType = dataType;

    // Success
    return true;
}

DataBus::AccessPermission DataBus::PropertyInfo::getAccessPermission() const
{
    return m_accessPermission;
}

bool DataBus::PropertyInfo::setAccessPermission(const AccessPermission accessPermission)
{
    // Check access permission
    if ((accessPermission < AccessPermission_ReadOnly) ||
        (accessPermission > AccessPermission_ReadWrite))
    {
        // Error, invalid access permission
        return false;
    }

    // Save access permission
    m_accessPermission = accessPermission;

    // Success
    return true;
}

QString DataBus::PropertyInfo::getName() const
{
    return m_name;
}

bool DataBus::PropertyInfo::setName(const QString &name)
{
    // Check name
    if (name.toUtf8().size() > STRING_MAX_LENGTH)
    {
        // Error, name is too long
        return false;
    }

    // Save name
    m_name = name;

    // Success
    return true;
}

QByteArray DataBus::PropertyInfo::toBinary() const
{
    // Check if property info is valid
    if (isValid() == false)
    {
        // Error, invalid property info
        return QByteArray();
    }

    // Create binary data
    QByteArray data;

    data.append(static_cast<char>(m_id));
    data.append(static_cast<char>(m_dataType));
    data.append(static_cast<char>(m_accessPermission));
    data.append(Value::toBinary(m_name));

    // Success
    return data;
}

bool DataBus::PropertyInfo::fromBinary(const QByteArray &data,
                                       const int startIndex)
{
    // Check input parameters
    if ((startIndex < 0) ||
        ((startIndex + 4) > data.size()))
    {
        // Error, invalid input parameters
        return false;
    }

    // Get Property ID
    quint8 id = static_cast<quint8>(data.at(startIndex));

    // Get Data Type
    DataType dataType = static_cast<DataType>(data.at(startIndex + 1));

    if ((dataType < DataType_Boolean) ||
        (dataType > DataType_ByteArray))
    {
        return false;
    }

    // Get Access Permission
    AccessPermission accessPermission = static_cast<AccessPermission>(data.at(startIndex + 2));

    if ((accessPermission < AccessPermission_ReadOnly) ||
        (accessPermission > AccessPermission_ReadWrite))
    {
        // Error, invalid access permission
        return false;
    }

    // Get Property Name
    QString name;

    if (Value::fromBinary(data, &name, startIndex + 3) == false)
    {
        // Error, failed to get Name
        return false;
    }

    if (name.toUtf8().size() > STRING_MAX_LENGTH)
    {
        // Error, name is too long
        return false;
    }

    // Save values
    m_id = id;
    m_dataType = dataType;
    m_accessPermission = accessPermission;
    m_name = name;

    // Success
    return true;
}
